/**
 *     This file is part of cesm-ws.
 *
 *     cesm-ws, Web Service for Community Earth System Model
 *
 *     Copyright (c) 2010, Purdue University and/or affilicates or thrid-party contributors as
 *     indicated by the @author tags or express copyright attribution statements
 *     applied by the authors. All third-party contributions are distributed under
 *     license by Purdue University.
 *
 *     cesm-ws is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with this distribution.  If not, see <http://www.gnu.org/licenses/>.
 */

package edu.purdue.rcac.cesm.ws.restful;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.xml.ws.WebServiceProvider;

import org.apache.log4j.Logger;

import edu.purdue.rcac.cesm.facade.ServiceFacade;
import edu.purdue.rcac.cesm.facade.ServiceFacadeLocal;
import edu.purdue.rcac.cesm.facade.bean.AllCaseInfoBean;
import edu.purdue.rcac.service.dispatch.ServiceDispatcherManagement.AuthDatabase;
import edu.purdue.rcac.service.dispatch.ServiceDispatcherManagement.SubmitType;
import edu.purdue.rcac.service.dispatch.ServiceDispatcherManagement.SubmitterImpLanguage;

/**
 * @author Han Zhang
 */

@WebServiceProvider
@Path("/rest")
public class CESMRestfulImpl implements CESMRestfulInterface {
	protected static final Logger log = Logger.getLogger(CESMRestfulImpl.class
			.getName());

	public static final SubmitType defaultSubmitType = SubmitType.GLOBUS;

	public static final SubmitterImpLanguage defaultSubmitterLang = SubmitterImpLanguage.JAVA;

	private ServiceFacadeLocal serviceFacade;

	public CESMRestfulImpl() {
		super();
		try {
			InitialContext ctx = new InitialContext();
			serviceFacade = (ServiceFacadeLocal) ctx
					.lookup(ServiceFacade.LOCAL_JNDI_BINDING);
		} catch (NamingException ne) {
			log.error(ne);
			serviceFacade = null;
		}
	}

	// /**
	// * Public Interface
	// */
	// // Create a new CCSM test case
	// @PUT
	// @Produces( { "application/xml", "application/json" })
	// @Path("createCase/{caseName}/{resolution}/{componentSet}/{allocation}/{machine}/")
	// public CreateCaseBean createCase(
	// @PathParam("resolution") String resolution,
	// @PathParam("componentSet") String componentSet,
	// @PathParam("allocation") String allocation,
	// @PathParam("machine") String machine,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("userName") String userName,
	// @HeaderParam("password") String password) throws Exception {
	//
	// Resolution resolutionEnum;
	// ComponentSet componentSetEnum;
	// log.debug("resolution: " + resolution);
	// log.debug("component set: " + componentSet);
	// log.debug("machine: " + machine);
	// try {
	// resolutionEnum = Resolution.fromString(resolution);
	// componentSetEnum = ComponentSet.fromString(componentSet);
	// Machine.fromString(machine.trim());
	// } catch (IllegalArgumentException iae) {
	// throw new Exception("input parameter is invalid", iae);
	// }
	// return serviceFacade.createCase(resolutionEnum, componentSetEnum,
	// allocation, machine, caseName, userName, password,
	// AuthDatabase.PortalDB);
	//
	// }
	//
	// // list all the configuration variables that can be changed
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("listConfigVars/{caseName}")
	// public ConfigVarListBean getConfigVarList(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getConfigVarList(userName, caseName, token);
	// }
	//
	// // get the current value of a configuration variable
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("queryConfigVar/{caseName}/{varname}")
	// public ConfigVarBean queryConfigVar(
	// @PathParam("varname") String varName,
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.queryConfigVar(varName, userName, caseName, token);
	// }
	//
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("setConfigVar/{caseName}/{varname}/{varvalue}")
	// public String setConfigVar(
	// @PathParam("varname") String varName,
	// @PathParam("varvalue") String varValue,
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.setConfigVar(varName, varValue, userName,
	// caseName, token);
	//
	// }
	//
	// // Configure a case
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("configureCase/{caseName}")
	// public ConfigureCaseResponse configureCase(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.configureCase(userName, caseName, token);
	// }
	//
	// // Reset configuration
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("resetConfig/{caseName}")
	// public ResetConfigResponse resetConfig(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.resetConfig(userName, caseName, token);
	//
	// }
	//
	// // Build and Run a CCSM case
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("runCase/{caseName}/{email}/{queueToRun}/{wallTime}/{ncpus}")
	// public RunCaseResponse runCase(@HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @PathParam("email") String email,
	// @PathParam("queueToRun") String queueToRun,
	// @PathParam("wallTime") String wallTime,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.runCase(userName, caseName, email, queueToRun,
	// wallTime, token);
	//
	// }
	//
	// // show all the cases owned by a user
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("showCases")
	// public ShowCasesResponse showCases(
	// @HeaderParam("userName") String userName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.showCases(userName, token);
	// }
	//
	// // cancel a case which is either in queue or running
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("cancelCase/{caseName}")
	// public CancelCaseResponse cancelCase(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.cancelCase(userName, caseName, token);
	// }
	//
	// // delete all the data related to a case from the system
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("deleteCase/{caseName}")
	// public DeleteCaseResponse deleteCase(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.deleteCase(userName, caseName, token);
	// }
	//
	// // query the status of a case
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("getJobStatus/{caseName}")
	// public GetJobStatusResponse getJobStatus(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getJobStatus(userName, caseName, token);
	// }
	//
	// // query the walltime usage
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("getUsedWallTime/{caseName}")
	// public GetUsedWallTimeResponse getUsedWallTime(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getUsedWallTime(userName, caseName, token);
	// }
	//
	// // query the CPU usage
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("getUsedCPUTime/{caseName}")
	// public GetUsedCPUTimeResponse getUsedCPUTime(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getUsedCPUTime(userName, caseName, token);
	// }
	//
	// // return output file location for download (http/ftp?)
	// @GET
	// @Produces( { "application/xml", "application/json" })
	// @Path("getOutputLocation/{caseName}")
	// public GetOutputLocationResponse getOutputLocation(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getOutputLocation(userName, caseName, token);
	// }
	//
	//
	// // return a boolean indicates if this token has been expired
	// @GET
	// @Produces( { "application/xml" })
	// @Path("isTokenValid")
	// public IsTokenValidResponse isTokenValid(
	// @HeaderParam("userName") String userName,
	// @HeaderParam("token") String token) throws Exception {
	// return serviceFacade.isTokenValid(userName, token);
	// }
	//
	// @GET
	// @Produces( { "application/xml" })
	// @Path("getCaseConfigInfo/{caseName}")
	// public GetCaseConfigInfoResponse getCaseConfigInfo(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getCaseConfigInfo(userName, caseName, token);
	// }
	//
	// @GET
	// @Produces( { "application/xml" })
	// @Path("getCaseRuntimeInfo/{caseName}")
	// public GetCaseRuntimeInfoResponse getCaseRuntimeInfo(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getCaseRuntimeInfo(userName, caseName, token);
	// }
	//
	// @GET
	// @Produces( { "application/xml" })
	// @Path("getCaseRuntimeInfo/{queueName}/{machine}")
	// public CheckJobsByUserResponse checkJobsByUser(
	// @HeaderParam("userName") String userName,
	// @PathParam("queueName") String queueName,
	// @PathParam("machine") String machine,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.checkJobsByUser(userName, queueName, machine,
	// token);
	// }
	//
	// @GET
	// @Produces( { "application/xml" })
	// @Path("getCaseRuntimeInfo/{caseName}/{envFile}")
	// public GetCaseConfigFileResponse getCaseConfigFile(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @PathParam("envFile") String envFile,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.getCaseConfigFile(userName, caseName, EnvFile
	// .valueOf(envFile), token);
	// }
	//
	// @GET
	// @Produces( { "application/xml" })
	// @Path("setCaseRuntimeInfo/{caseName}/{envFile}")
	// public SetCaseConfigFileResponse setCaseConfigFile(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @PathParam("envFile") String envFile,
	// @FormParam("content") String content,
	// @HeaderParam("token") String token) throws Exception {
	//
	// return serviceFacade.setCaseConfigFile(userName, caseName, EnvFile
	// .valueOf(envFile), content, token);
	// }
	//
	// @GET
	// @Produces( { "application/xml" })
	// @Path("setCaseRuntimeInfo/{caseName}")
	// public SetConfigVarListResponse setConfigVarList(
	// @HeaderParam("userName") String userName,
	// @PathParam("caseName") String caseName,
	// @FormParam("varList") String varList,
	// @FormParam("separator") String separator,
	// @HeaderParam("token") String token) throws Exception {
	// List<KeyValueEntry> pairs = new ArrayList<KeyValueEntry>();
	//
	// for (String str : varList.split(separator)) {
	// pairs.add(KeyValueEntry.fromString(str));
	// }
	// return serviceFacade.setConfigVarList(userName, caseName, pairs, token);
	// }
	//
	@GET
	@Produces({ "application/xml" })
	@Path("getCaseInfoList/")
	public AllCaseInfoBean getCaseInfoList(
			@HeaderParam("userName") String userName,
			@HeaderParam("token") String token) throws Exception {
		return serviceFacade.listAllCaseInfo(userName, token);
	}

	// return a token if user is authenticated, otherwise return ""
	@GET
	@Produces({ "application/xml" })
	@Path("authenticate/")
	public String authenticate(@HeaderParam("userName") String userName,
			@HeaderParam("password") String password) throws Exception {

		return serviceFacade.authenticate(userName, password,
				AuthDatabase.PortalDB);
	}

	@GET
	@Produces({ "application/xml" })
	@Path("echo/{str}")
	public String echo(@PathParam("str") String str) {
		return "Hello, " + str;
	}
}
